package com.chikitbd.shadowsocks.service;


import com.chikitbd.common.Crawler;
import com.chikitbd.common.PropertiesLoader;
import com.chikitbd.common.Util;
import com.chikitbd.freev2ray.bean.guinconfig.V2RayConfig;
import com.chikitbd.freev2ray.bean.guinconfig.Vmess;
import com.chikitbd.shadowsocks.entity.ssr.Configs;
import com.chikitbd.shadowsocks.entity.ssr.ShadowsocksRConfig;
import com.gargoylesoftware.htmlunit.BrowserVersion;
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.HtmlElement;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;

public class CrawlerShadowsocksRImpl implements Crawler {

    private Gson gson = new GsonBuilder().setPrettyPrinting().create();

    public static void main(String[] args) {

        try {
            CrawlerShadowsocksRImpl crawlerShadowsocksRImpl = new CrawlerShadowsocksRImpl();
            crawlerShadowsocksRImpl.start();
            System.out.println("完成！");
        } catch (Exception exception) {
            System.out.println("异常：" + exception);
            exception.printStackTrace();
        }
    }


    /**
     * @throws
     * @Title: start
     * @Description: 主方法启动
     * @Author: LanceBD
     * @Date: 2018年9月12日
     * void
     */
    public void start() throws IOException {
        String originalGUIConfig = "";
        HtmlPage page;
        try (WebClient webClient = new WebClient(BrowserVersion.CHROME);) {
            page = webClient.getPage(PropertiesLoader.SHADOWSOCKS_URL);
            originalGUIConfig = this.readConfig(PropertiesLoader.SHADOWSOCKSR_PATH);
            this.writeConfig(originalGUIConfig, page, PropertiesLoader.SHADOWSOCKSR_PATH);
        }
    }

    @Override
    public String readConfig(String filePath) throws IOException {
        return Util.readFile(filePath);
    }

    @Override
    public boolean writeConfig(String originalConfig, HtmlPage page, String filePath) throws IOException {
        ShadowsocksRConfig shadowsocksRConfig = gson.fromJson(originalConfig.toString(), ShadowsocksRConfig.class); // 读取原来的配置文件, 通过Gson转化为JavaBean
        shadowsocksRConfig.setConfigs(getShadowsocksConfigs(page));
        String crawlerJsonResult = gson.toJson(shadowsocksRConfig);
        boolean result = Util.writeFile(crawlerJsonResult, filePath);
        if (result) {
            Util.printfSuccess("SSR-iShadowsocks");
        }
        return result;
    }


    /**
     * @param page
     * @return List<Configs>
     * @throws
     * @Title: getShadowsocksConfigs
     * @Description: 通过Element的ID爬取相关的内容
     * @Author: LanceBD
     * @Date: 2018年9月12日
     */
    private List<Configs> getShadowsocksConfigs(HtmlPage page) throws IOException {
        List<Configs> crawlerSever = new ArrayList<Configs>();
        List<Vmess> vmesss = new ArrayList<Vmess>();
        for (int i = 0; i < PropertiesLoader.SERVER_INFOS.size(); i++) {

            String serverInfo = PropertiesLoader.SERVER_INFOS.get(i);

            if (!serverInfo.contains("#")) {
                HtmlElement v2rayDiv = page.getHtmlElementById(serverInfo);
                String vmessEncodeStr = v2rayDiv.getAttribute("data-clipboard-text");
                String vmessDecodeStr = Util.base64decod(vmessEncodeStr);
                HashMap<String, Object> map = gson.fromJson(vmessDecodeStr, HashMap.class);
                System.out.println(map);
                Vmess vmessTmp = new Vmess();
                vmessTmp.setAddress((String) map.get("add"));
                vmessTmp.setPort(Integer.parseInt( (String)map.get("port")));
                vmessTmp.setId((String) map.get("id"));
//                vmessTmp.setId(UUID.randomUUID().toString().toLowerCase());
                vmessTmp.setAlterId(((Double) map.get("aid")).intValue());
                vmessTmp.setSecurity((String) "auto");
                vmessTmp.setNetwork((String) map.get("net"));
                vmessTmp.setRemarks((String) map.get("ps"));
                vmessTmp.setHeaderType((String) map.get("type"));
                vmessTmp.setRequestHost("microsoft.com");
                vmessTmp.setPath((String) map.get("path"));
                vmessTmp.setStreamSecurity((String) map.get("tls"));
                vmessTmp.setAllowInsecure("");
                vmessTmp.setConfigType(1);
                vmessTmp.setTestResult("");
                vmessTmp.setSubid("");
                vmessTmp.setConfigVersion(((Double) map.get("v")).intValue());
                vmesss.add(vmessTmp);
//                System.out.println(vmessTmp);
            } else {
                String[] strServerInfo = Util.getServerElement(PropertiesLoader.SERVER_INFOS.get(i));
                Configs config = new Configs();
                try {
                    HtmlElement ip_div = page.getHtmlElementById(strServerInfo[0]);
                    HtmlElement password_div = page.getHtmlElementById(strServerInfo[1]);
                    HtmlElement port_div = page.getHtmlElementById(strServerInfo[2]);

                    if (ip_div == null || ip_div.asText().equals("")) {
                        continue;
                    }
                    config.setServer(ip_div.asText());
                    config.setPassword(password_div.asText());
                    config.setServer_port(Integer.parseInt(port_div.asText()));
                    config.setMethod("aes-256-cfb");

                    if (strServerInfo.length > 3) {
                        config.setProtocol(strServerInfo[3]);
                        config.setObfs(strServerInfo[4]);
                    } else {
                        config.setProtocol("origin");
                        config.setObfs("plain");
                    }

                    config.setEnable(true);
                    config.setUdp_over_tcp(false);
                    crawlerSever.add(config);

//			System.out.println("ip_div: " + ip_div.asText());
//			System.out.println("port_div: " + port_div.asText());
//			System.out.println("password_div: " + password_div.asText());
//			System.out.println(password_div.asXml());
//				System.out.println(crawlerSever);
                } catch (Exception e) {
                    System.out.println(e);
                }
            }
        }
        this.setV2RayIShadowsocks(vmesss);

        return crawlerSever;
    }


    private void setV2RayIShadowsocks(List<Vmess> vmesss) {

        if(!PropertiesLoader.SET_V2RAY_ISHADOWSOCKS.equals("Y") || vmesss.size() <= 0){
            return;
        }

        String originalConfig = null;
        try {
            originalConfig = Util.readFile(PropertiesLoader.V2RAY_CONFIG_CLASS_PATH);
            V2RayConfig v2RayConfig = gson.fromJson(originalConfig.toString(), V2RayConfig.class);

            v2RayConfig.getVmess().clear();
            v2RayConfig.getVmess().addAll(vmesss);
            v2RayConfig.setIndex(2);

            // 将新的配置文件通过Gson转化为JSON格式文本
            String crawlerJsonResult = gson.toJson(v2RayConfig);
            boolean result = Util.writeFile(crawlerJsonResult, PropertiesLoader.V2RAY_PATH + PropertiesLoader.GUI_N_CONFIG);
            if (result) {
                Util.printfSuccess("V2Ray-iShadowsocks");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}
